/*
 * pi3's Linux kernel Runtime Guard
 *
 * Component:
 *  - Intercept 'wake_up_new_task' function
 *
 * Notes:
 *  - We are maintianing Red-Black tree of pid's for Exploit Detection feature.
 *    When process forks, child must be tracked as well! We need to update RB tree.
 *
 * Caveats:
 *  - Previous version was hooking 'do_fork' function.
 *
 * Timeline:
 *  - Created: 18.IX.2017
 *
 * Author:
 *  - Adam 'pi3' Zabrocki (http://pi3.com.pl)
 *
 */

#include "../../../../p_lkrg_main.h"


char p_wake_up_new_task_kretprobe_state = 0;

static struct kretprobe p_wake_up_new_task_kretprobe = {
    .kp.symbol_name = "wake_up_new_task",
    .handler = p_wake_up_new_task_ret,
    .entry_handler = p_wake_up_new_task_entry,
    .data_size = sizeof(struct p_wake_up_new_task_data),
    /* Probe up to 40 instances concurrently. */
    .maxactive = 40,
};


int p_wake_up_new_task_entry(struct kretprobe_instance *p_ri, struct pt_regs *p_regs) {

   struct task_struct *p_task = (struct task_struct *)p_regs_get_arg1(p_regs);
   pid_t p_pid;
   struct p_ed_process *p_tmp;
   unsigned long p_flags;

   if (p_task) {
      p_pid = task_pid_nr(p_task);
      p_tasks_write_lock_by_pid(p_pid,&p_flags);
//      if (!(p_task->flags & PF_KTHREAD || is_global_init(p_task))) {
      if (p_is_ed_task(p_task)) {
         int p_ret;

         if ( (p_ret = p_dump_task_f(p_task)) != 0) {
            if (p_ret == 1) {
               // Update process
               if ( (p_tmp = p_find_ed_by_pid(p_pid)) != NULL) {
                  // This process is on the ED list - update information!
                  p_print_log(P_LKRG_INFO, "<wake_up_new_task> Updating ED pid[%d]\n",p_pid);
                  p_update_ed_process(p_tmp, p_task, 1);
#ifdef P_LKRG_TASK_OFF_DEBUG
                  p_debug_off_flag_reset(p_tmp, 61);
#endif
                  p_reset_ed_flags(p_tmp);
               }
            } else {
               p_print_log(P_LKRG_WARN,
                      "<Exploit Detection> Error[%d] when trying to add process[%d |%s] for tracking!\n",
                                                                p_ret, p_pid, p_task->comm);
            }
         }
      }
      p_tasks_write_unlock_by_pid(p_pid,&p_flags);
   }

   p_ed_enforce_validation();

   return 0;
}


int p_wake_up_new_task_ret(struct kretprobe_instance *ri, struct pt_regs *p_regs) {

//   p_ed_enforce_validation();

   return 0;
}


GENERATE_INSTALL_FUNC(wake_up_new_task)
